# -*- coding: utf-8 -*-

'''
Created on 31/01/2010

@author: joger
'''
import wx
import sys
import os
import re
import wx.lib.customtreectrl as CT

from imagenes import images
from contrasenhas.modelo import Modelo
from comun import mensageError as msje, mensageAlerta as msja, mensajePregunta as msjp, validarNombreFichero, validarClave, validarNombreCategoria

class Controlador():
    '''
    classdocs
    '''

    def __init__(self,vista):
        '''
        Constructor
        '''
        
        #Datos de conexión
        self.db = ''
        self.password = ''
        self.nombreBD = ''
        self.home = os.getenv("HOME")
        self.rutaBD = "/.tibisay/dbclaves/"
        self.itemsCateorias = [] 
        
        self.vista = vista
        self.modelo = Modelo(self)
        
        #Verificamos la existencia de la ruta donde se almacenan las base de datos
        if not self.verificarExisteRutaBD():
            exit()
        #self.listaImagenes = wx.ImageList(16, 16)
        #self.imagen = self.listaImagenes.Add(images.getNewEntryBitmap())
    
    
    def deshabilitarTools(self):
        
        if not self.nombreBD:
            self.habilitarCerrarBD(False)
            self.habilitarAnhadirG(False)
        
        if not self.vista.treePresionado:
            self.habilitarEditarG(False)
            self.habilitarEliminarG(False)
            self.habilitarCrearClave(False)
            self.habilitarVerClave(False)
            self.habilitarEliminarClave(False)
    
    def habilitarCerrarBD(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idCerrarBD,valor)
        self.vista.itemCEBD.Enable(valor)
    
    
    def habilitarAnhadirG(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idAnhadirC,valor)
        self.vista.itemAC.Enable(valor)
        
    def habilitarEditarG(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idEditarC,valor)
        self.vista.itemEC.Enable(valor)
    
    def habilitarEliminarG(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idEliminarC,valor)
        self.vista.itemELC.Enable(valor)
    
    def habilitarCrearClave(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idCrearClave,valor)
        self.vista.itemCC.Enable(valor)
         
    
    def habilitarVerClave(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idVerClave,valor)
        self.vista.itemVEC.Enable(valor)
    
    def habilitarEliminarClave(self,valor):
        self.vista.parent.tb.EnableTool(self.vista.idEliminarClave,valor)
        self.vista.itemECL.Enable(valor)
        
    def verificarExisteRutaBD(self):
        
        if not os.path.isdir(self.home + self.rutaBD):
            if msjp(self.vista.ventanaHija,"La ruta " + self.home + self.rutaBD + " no existe. Para poder continuar con la ejecución debe crear el directorio. ¿Desea crear el directorio?"):
                try:
                    os.makedirs(self.home + self.rutaBD)
                except:
                    msja(self.vista,"Error al momento de querer crear el directorio %s . El sistema operativo arrojó el sigueinte error: %s" % (self.home + self.rutaBD,str(sys.exc_info()[1])))
            
                    return False
            else:
                return False

        return True
    
    def verificarExisteBD(self,nombre):
        if os.path.isfile(self.home + self.rutaBD + nombre + ".dat"):
            msje(self.vista.ventanaHija,"Ya existe la base de datos " + nombre + ". Pruebe ingresando otro nombre")
            return False
        
        return True
        
    def abrirBD(self,nombre,clave):
        
        nombre = nombre.encode('utf8')
        clave = clave.encode('utf8')
        if nombre == "":
            msja(self.vista.ventanaHija,"Debe ingresar el nombre de la base de datos")
        elif clave == "":
            msja(self.vista.ventanaHija,"Debe ingresar una clave")
        else:
            #Verificamos si existe la carpeta tibisay
        
            #Verificamos si existe la base de datos
        
            #Verificamos que hayan permisos de escritura en la carpeta
            
            r = self.listarCategorias(nombre,clave)
            if (type(r).__name__ == 'bool' and r) or type(r).__name__ == 'list':
                self.vista.ventanaHija.cerrarVentana(0)
            
                
    
    def verificarCerrarBD(self,evt):
        
        
        #self.borrarCategorias()
        if msjp(self.vista,"¿Está seguro que desea cerrar la base de datos?"):
            self.cerrarBD()
            
            
    
    def cerrarBD(self):
        
        self.vista.txtPanelC.SetLabel("Cerrando la base de datos: " + self.nombreBD)
        
        self.habilitarCerrarBD(False)
        self.habilitarAnhadirG(False)
        self.habilitarEditarG(False)
        self.habilitarEliminarG(False)
        self.habilitarCrearClave(False)
        self.habilitarEliminarClave(False)
        self.habilitarVerClave(False)
        
        ##self.vista.tree.UnselectAll()
        
        self.db = ""
        self.password = ""
        self.nombreBD = ""
        self.vista.treePresionado = None
        #self.modelo.rutaBD = ""
        #self.modelo.diccionarioDatos = {}
        self.borrarCategorias()
        self.borrarVistaClaves()
        
    def verificarBDAbierta(self,evt):
        
        #print 'Probando'
        idElemento = evt.GetId()
        #print self.db +'== "" and '+ self.password +' == ""'
        #Verificamos que no haya una base de datos abierta
        if self.db == "" or self.password == "" or self.nombreBD == "":
            #Dependiendo del id del tool que fue pinchado procedemos
            if idElemento == self.vista.idCrearBD or idElemento == self.vista.idMenuCrearBD:
                self.vista.crearBD()
            elif idElemento == self.vista.idAbrirBD or idElemento == self.vista.idMenuAbrirBD:
                self.vista.abrirBD()
                
        elif msjp(self.vista,"Existe una base de datos abierta ¿Desea cerrarla?"):
            
            self.cerrarBD()
            
            if idElemento == self.vista.idCrearBD:
                self.vista.crearBD()
            elif idElemento == self.vista.idAbrirBD:
                self.vista.abrirBD()
            
        
    def crearBaseDatos(self,nombre,clave,confirmacion):
        
        varNombre = nombre.GetValue().encode('utf8')
        varClave = clave.GetValue().encode('utf8')
        varConfirmacion = confirmacion.GetValue().encode('utf8')
        
        if varNombre == "":
            #self.vista.ventanaHija.msja(self.vista.ventanaHija,"Debe ingresar el nombre de la base de datos")
            msja(self.vista.ventanaHija,"Debe ingresar el nombre de la base de datos")
            nombre.SetFocus()
        elif varClave == "":
            #self.vista.ventanaHija.msja(self.vista.ventanaHija,"Debe ingresar una clave")
            msja(self.vista.ventanaHija,"Debe ingresar una clave")
            clave.SetFocus()
        elif varConfirmacion == "":
            #self.vista.ventanaHija.msja(self.vista.ventanaHija,"Debe ingresar la confiramción de la clave")
            msja(self.vista.ventanaHija,"Debe ingresar la confiramción de la clave")
            confirmacion.SetFocus()
        elif varClave != varConfirmacion:
            #self.vista.ventanaHija.msje(self.vista.ventanaHija,"La clave y la confirmación no son iguales. Ingreselas de nuevo")
            msje(self.vista.ventanaHija,"La clave y la confirmación no son iguales. Ingreselas de nuevo")
            clave.SetFocus()
        else:
            
            
            #Verificamos que exita la ruta donde se almacenan las bases de datos
            if not self.verificarExisteRutaBD():
               return
        
            #Verificamos si ya existe una base de datos
            if not self.verificarExisteBD(varNombre):
               return
           
            #Verificamos que hayan permisos de escritura en la carpeta
            #Verificamos que el nombre sea un campo válido para nombre
            nomVal = validarNombreFichero(varNombre)
            claveVal = validarClave(varClave)
            if not nomVal:
                msje(self.vista.ventanaHija,u"¡Nombre de base de datos no válido!\n\n"
                                           +u"1) No debe ingresar nombres con espacios en blancos\n"
                                           +u"2) Prohibido los caracteres especiales: !\"?¿¡&%$#\n"
                                            )
            #Verificamos que la clave sea un campo valido de clave
            if not claveVal:
                msje(self.vista.ventanaHija,"¡La clave tiene un formato que no es válido!")
            
            if nomVal and claveVal:
                flag = self.modelo.crearBaseDatos(varNombre,varClave)
                if flag:
                    self.vista.ventanaHija.parent.txtPanelC.SetLabel("Conectado a la base de datos " + varNombre)
                    msja(self.vista.ventanaHija,"La base de datos " + varNombre + " fue creada existosamente")
                    self.vista.ventanaHija.cerrarVentana(0)
                    self.vista.ventanaHija = None
                
                    self.habilitarCerrarBD(True)
                    self.habilitarAnhadirG(True)
                
                else:
                    msje(self.vista.ventanaHija,u"¡Error! No se pudo crear la base de datos")
        
    def listarContrasegnas(self):
        
        self.borrarVistaClaves()
        self.modelo.listarContrasegnas()
        
        for key,data in self.modelo.diccionarioDatos.items():
            index = self.vista.listCtrl.InsertImageStringItem(sys.maxint,data[0],self.vista.imagenLista)
            self.vista.listCtrl.SetStringItem(index, 1, data[1])
            self.vista.listCtrl.SetStringItem(index, 2, data[2])
            self.vista.listCtrl.SetStringItem(index, 3, data[3])
            #self.vista.listCtrl.SetStringItem(index, 4, data[4])
            self.vista.listCtrl.SetItemData(index,key)
        
        self.vista.itemListeleccionado = None
        self.habilitarVerClave(False)
        self.habilitarEliminarClave(False)
       
    def listarCategorias(self,nombre,clave):
        
        
        categorias = self.modelo.listarCategorias(nombre,clave)
        if categorias:
            #self.vista.tree.DeleteAllItems()
            for c in categorias:
                child = self.vista.tree.AppendItem(self.vista.root,c)
                self.itemsCateorias.append(child)
                self.vista.tree.SetPyData(child, None)
                self.vista.tree.SetItemImage(child, self.vista.fldropenidx, wx.TreeItemIcon_Normal)
                self.vista.tree.SetItemImage(child, self.vista.fldridx, wx.TreeItemIcon_Expanded)
            
            self.vista.txtPanelC.SetLabel(u"Listando categorías de la base de datos: " + self.nombreBD)
            return True
        
        
        
        return categorias
        
       
    def borrarVistaClaves(self):
        
        #print self.vista.listCtrl.GetItemCount()
        self.vista.listCtrl.DeleteAllItems()
        
    def borrarCategorias(self):
        
        self.vista.tree.DeleteChildren(self.vista.root)
        self.itemsCateorias = []
    
    
    def crearCategoria(self,nombre):
        
        flag = True
        varNombre = nombre.GetValue().strip()
        #Verificamos que el grupo no esté vacío
        if varNombre == "":
            #self.vista.ventanaHija.msja(self.vista.ventanaHija,"Debe ingresar el nombre de la base de datos")
            msja(self.vista.ventanaHija,"¡Debe ingresar el nombre de la categoría!")
            nombre.SetFocus()
            return
        
        #Patron que va a buscar si la cadena tiene:
        # ! $ % & / ( ) = ? ¿
        #p = re.compile('(.*\..*)|(.*,.*)|(.*!.*)|(.*/.*)|(.*\s.*)')
        #Verificamos que el nombre de la categoría no tengo espacios en blanco
        if not validarNombreCategoria(self.vista.ventanaHija,varNombre):
            #msja(self.vista.ventanaHija,"El nombre de la categoría no puede contener:\n\n"
            #                            + "1) Espacios en blanco\n"
            #                            + "2) Caracteries especiales !\"\#$%&/()=?¿!.,"
            #                            )
            nombre.SetFocus()
            return
        
        
        
        #Verificamos que el grupo no se encuentra en la lista de grupos
        for c in self.itemsCateorias:
            if self.vista.tree.GetItemText(c).lower() == nombre.GetValue().lower():
                flag = False
                break
        
        if not flag:
            msje(self.vista.ventanaHija,"Ya existe una categoría con ese nombre")
        else:
            child = self.vista.tree.AppendItem(self.vista.root,nombre.GetValue())
            self.itemsCateorias.append(child)
            self.vista.tree.SetPyData(child, None)
            self.vista.tree.SetItemImage(child, self.vista.fldropenidx, wx.TreeItemIcon_Normal)
            self.vista.tree.SetItemImage(child, self.vista.fldridx, wx.TreeItemIcon_Expanded)
            self.vista.ventanaHija.cerrarVentana(0)
            
        
    def editarCategoria(self,nuevaCategoria):
        
        categoria = self.vista.tree.GetItemText(self.vista.treePresionado).encode("utf8")
        varNuevaCategoria = nuevaCategoria.GetValue().encode("utf8")
        #Verificamos que el grupo no esté vacío
        if varNuevaCategoria == "":
            msja(self.vista.ventanaHija,u"Debe ingresar el nuevo nombre de la categoría")
            nuevaCategoria.SetFocus()
            return
        
        #Verificamos que el nuevo nombre de la categoría sea válido
        if not validarNombreCategoria(self.vista.ventanaHija,varNuevaCategoria):
            nuevaCategoria.SetFocus()
            return
        
        #Preguntamos al usuari si está seguro de querer editar
        if not msjp(self.vista.ventanaHija,u"¿Está seguro de querer editar el nombre de la categoría " + categoria + " por " + varNuevaCategoria + "?"):
            return
        
        
        #Verificamos que el grupo no se encuentra en la lista de grupos
        for c in self.itemsCateorias:
            if self.vista.tree.GetItemText(c).lower().encode("utf8") == nuevaCategoria.GetValue().lower().encode("utf8"):
                msje(self.vista.ventanaHija,u"Ya existe una categoría con ese nombre")
                return
                
        #Verificamos la existencia de la categoria en la base de datos, de existir procedemos a editarla
        if self.verificarExistenciaCategoria(categoria):
            self.modelo.editarCategoria(categoria,nuevaCategoria.GetValue())
            
            #Verificamos que el nombre de la nueva categoría no exista ya en la base de datos
            #if not self.verificarExistenciaCategoria(nuevaCategoria.GetValue()):
            #    self.modelo.editarCategoria(categoria,nuevaCategoria.GetValue())
            #    self.vista.ventanaHija.cerrarVentana(0)
            #else:
            #    msje(self.vista.ventanaHija,"Ya existe una categoría con ese nombre")
        
        
        #Procedemos a añadir la categoria al treectrl
        self.vista.tree.SetItemText(self.vista.treePresionado,nuevaCategoria.GetValue())
        self.vista.ventanaHija.cerrarVentana(0)
        
    def verificarExistenciaCategoria(self,categoria):
        #print categoria
        categorias = self.modelo.listarPorCategoria(categoria)
        #print categorias
        
        if len(categorias) > 0 :
            return True
        
        return False        
    
    def eliminarCategoria(self):
        
        #Verificamos que haya una categoría seleccionada
        if not self.vista.treePresionado:
            msja(self.vista,u"Debe seleccionar una categoría para poder eliminarla")
            return
        
        categoria = self.vista.tree.GetItemText(self.vista.treePresionado)
        #Preguntamos al usuario si desea realmente eliminar la categoria
        if not msjp(self.vista,u"Desea realmente eliminar la caregoría: " + categoria):
            return
        
        if self.modelo.eliminarCategoria():
            
            #El uso de esta variable está explicado en el método self.vista.treeSeleccionado
            self.vista.botonEliminarCategoria = True

            #Procedemos a elminar los de trectrl
            #self.vista.tree.UnselectAll()#Delete(self.vista.treePresionado)
            #Estoy resolviendo este probelma
            self.vista.tree.DeleteChildren(self.vista.treePresionado)
            self.vista.tree.Delete(self.vista.treePresionado)
            self.itemsCateorias.remove(self.vista.treePresionado)
            self.vista.treePresionado = None
            #Borramos las claves de la vista
            self.borrarVistaClaves()

            #self.listarCategorias(self.nombreBD,self.password)
            
            #Deshabilitamos los botones
            self.habilitarEditarG(False)
            self.habilitarEliminarG(False)
            self.habilitarCrearClave(False)
    
    def verificarDatosIngClave(self,iTitulo,iUsuario,iClave,iConfirmacion,iComentario):
        
        #Verificamos que este seleccioada una categoría
        if not self.vista.treePresionado:
            msja(self.vista,u"Debe seleccionar una categoría para poder añadirle una contraseña")
            return False
        
        #Verificamos los campo obligatrios
        if iTitulo.GetValue() == "":
            msja(self.vista.ventanaHija,u"Debe ingresar el título de la contraseña")
            iTitulo.SetFocus()
            return False
        elif iUsuario.GetValue() == "":
            msja(self.vista.ventanaHija,u"Debe ingresar el nombre del usuario")
            iUsuario.SetFocus()
            return False
        elif iClave.GetValue() == "":
            msja(self.vista.ventanaHija,u"Debe ingresar la contraseña")
            iClave.SetFocus()
            return False
        elif iConfirmacion.GetValue() == "":
            msja(self.vista.ventanaHija,u"Debe ingresar la confirmación")
            iConfirmacion.SetFocus()
            return False
        
        
        #Verificamos que la clave y la confirmacion sean iguales
        if iClave.GetValue() != iConfirmacion.GetValue():
            msja(self.vista.ventanaHija,u"La contraeña y la confirmación no son iguales")
            iClave.SetFocus()
            return False
        
        return True
        
    def crearClave(self,iTitulo,iUsuario,iClave,iConfirmacion,iComentario):
        
        titulo = iTitulo.GetValue()
        usuario = iUsuario.GetValue()
        clave = iClave.GetValue()
        #confirmacion = iConfirmacion.GetValue()
        comentario = iComentario.GetValue()
        
        if not self.verificarDatosIngClave(iTitulo,iUsuario,iClave,iConfirmacion,iComentario):
            return
        
        categoria = self.vista.tree.GetItemText(self.vista.treePresionado)
        if self.modelo.buscarClave(categoria + "." + titulo):
            msja(self.vista.ventanaHija,u"Ya existe una clave con el título "+ titulo + u" para la categoría " + categoria)
            iTitulo.SetFocus()
            return
        
        self.modelo.ingresarClave(categoria,titulo,usuario,clave,comentario)
        #Procedemos a refescar el listctrl
        self.listarContrasegnas()
        self.vista.ventanaHija.cerrarVentana(0)
    
    def modificarClave(self,tituloOriginal,iTitulo,iUsuario,iClave,iConfirmacion,iComentario):
        
        titulo = iTitulo.GetValue()
        usuario = iUsuario.GetValue()
        clave = iClave.GetValue()
        #confirmacion = iConfirmacion.GetValue()
        comentario = iComentario.GetValue()
        
        if not self.verificarDatosIngClave(iTitulo,iUsuario,iClave,iConfirmacion,iComentario):
            return
        
        categoria = self.vista.tree.GetItemText(self.vista.treePresionado)
        if titulo != tituloOriginal:
            if self.modelo.buscarClave(categoria + "." + titulo):
                msja(self.vista.ventanaHija,u"Ya existe una clave con el título "+ titulo + u" para la categoría " + categoria)
                iTitulo.SetFocus()
                return
        
        
        self.modelo.modificarClave(categoria,tituloOriginal,titulo,usuario,clave,comentario)
        #Procedemos a refescar el listctrl
        self.listarContrasegnas()
        self.vista.ventanaHija.cerrarVentana(0)
        
    
    def eliminarClave(self):
        
        if msjp(self.vista,"¿Está seguro que desea eliminar la clave?"):
            
            categoria = self.vista.tree.GetItemText(self.vista.treePresionado)
            titulo = self.vista.listCtrl.GetItemText(self.vista.itemListeleccionado)
            #print "Cat: *" + categoria + "***" + "Titulo: ***" + titulo + "**"
            if self.modelo.eliminarClave(categoria,titulo):
                self.vista.listCtrl.DeleteItem(self.vista.itemListeleccionado)
                self.vista.itemListeleccionado = None
                self.habilitarVerClave(False)
                self.habilitarEliminarClave(False)
                
